﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;

namespace TwlNS {
	class CircularField : Environment {
		protected double _Radius;
		public double Radius {
			get { return _Radius; }
		}

		public CircularField(double radius) {
			_Radius = radius;
			_Width = 2*radius;
			_Height = 2*radius;
		}

		public override void AddNodesAndRandomDistribute(List<Node> nodes) {
			Random r = UseRandomVariableSeed?new Random(RandomVariableSeed):new Random();
			Coord center=new Coord(Radius,Radius);
			foreach (Node n in nodes) {
				while (true) {
					double rand_value = r.NextDouble();
					double x = rand_value * _Width;
					rand_value = r.NextDouble();
					double y = rand_value * _Height;
					Coord coord = new Coord(x, y);	
					if(coord.distance(center)<=Radius) {
						n.Location = coord;
						break;
					}
				//	System.Threading.Thread.Sleep(1);
				}
			}
			base.AddNodesAndRandomDistribute(nodes);
		}

		public double GetCoverage2(int minCoverage, int seti) {
			int width = (int) (2*Radius);
			Bitmap bmp = new Bitmap(width, width);
			Graphics gBmp = Graphics.FromImage(bmp);
			gBmp.CompositingMode = CompositingMode.SourceOver;
			Brush b = new SolidBrush(Color.FromArgb(0xFF,0x00,00,0xFF));
			Pen pen=new Pen(b);

			gBmp.FillEllipse(b, 0, 0, width, width);  //Fill bitmap with inital color;
			b = new SolidBrush(Color.FromArgb(0x01, 0xFF, 00, 00));
			pen = new Pen(b,1);
			if(minCoverage>128)
				throw new Exception("minConverage of "+minCoverage+" is not supported, 128 is maximum value for it!");
			/*
			//Testing code
			for(int i=0;i<255;i++){
				Console.WriteLine(i+" "+bmp.GetPixel(width / 2, width/2).R);
				gBmp.FillRectangle(b,0,0,width,width);
			}*/
			int covered = 0;
			int not_convered = 0;
			foreach (Node n in _Nodes) {
				if(!n.SetNumbers.Contains(seti))
					continue;
				int x = (int) n.Location.X;
				int y = (int) n.Location.Y;
				var rect = new Rectangle(x-SensingRadius, y-SensingRadius,2*SensingRadius,2*SensingRadius);
				gBmp.FillEllipse(b,rect);
				//gBmp.DrawEllipse(pen,rect);
			}
			Coord bmpCenter = new Coord(Radius, Radius);
			for (int y = 0; y < (int)Radius * 2; y++){
				for (int x = 0; x < (int) Radius*2; x++){
					Coord coord = new Coord(x, y);
					if (coord.distance(bmpCenter) > Radius)
						continue;
					//if (bmp.GetPixel(x, y).B==0)
					//	continue;
					if (bmp.GetPixel(x, y).R >= minCoverage)
						covered++;
					else
						not_convered++;
				}
			}
			gBmp.Dispose();
			//bmp.Save(@"D:\Project\TwlNS\test.bmp");
			bmp.Dispose();
			if (covered + not_convered != 0)
				return (double)covered / (covered + not_convered);
			return 0.0;

		}

        public double GetCoverage(int minCoverage, int seti)
        {
            int covered = 0;
            int not_convered = 0;
            Coord center = new Coord(Radius, Radius);
            for (int y = 0; y < (int)Radius * 2; y++)
            {
                for (int x = 0; x < (int)Radius * 2; x++)
                {
                    Coord coord = new Coord(x, y);
                    if (coord.distance(center) <= Radius)
                    {
                        not_convered++;
                        int numCoverage = 0;
                        foreach (Node n in _Nodes)
                        {
                            if (n is SensorNode && n.Sinked && n.Activated && n.Location.distance(coord) <= SensingRadius && n.SetNumbers.Contains(seti))
                            {
                                numCoverage++;
                            }
                        }
                        if (numCoverage >= minCoverage)
                        {
                            covered++;
                            not_convered--;
                        }
                    }
                }
            }
            if (covered + not_convered != 0)
                return (double)covered / (covered + not_convered);
            return 0.0;
        }
	}
}
